package com.uwaterloo.interviewme.requsthandler;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.content.Context;
import android.content.res.Resources;

import com.uwaterloo.interviewme.R;
import com.uwaterloo.interviewme.common.DetailInfoKeys;
import com.uwaterloo.interviewme.common.InterviewKeys;
import com.uwaterloo.interviewme.common.OpCode;
import com.uwaterloo.interviewme.common.RequestKeys;
import com.uwaterloo.interviewme.common.ResponseKeys;
import com.uwaterloo.interviewme.exception.ServerException;
import com.uwaterloo.interviewme.model.DetailInfo;
import com.uwaterloo.interviewme.model.Interview;
import com.uwaterloo.interviewme.model.Request;
import com.uwaterloo.interviewme.model.Response;

/**
 * The Class SocketRequestHandler implements {@link RequestHandler} using socket.
 */
public class SocketRequestHandler extends RequestHandler {

	/** The socket. */
	private Socket socket;

	/** The out to server. */
	private PrintWriter outToServer;

	/** The from server. */
	private BufferedReader fromServer;
	
	/**host & port*/
	private String host;
	private int port;
	
	public SocketRequestHandler(Context ctx) {
		Resources res = ctx.getResources();
		host= res.getString(R.string.host);
		port = Integer.parseInt(res.getString(R.string.port));
	}

	/**
	 * Open.
	 */
	private void open() throws ServerException{
		try {
			socket = new Socket(host, port);
			fromServer = new BufferedReader(new InputStreamReader(socket.getInputStream()));
			outToServer = new PrintWriter(socket.getOutputStream(), true);
		} catch (Exception e) {
			throw new ServerException(e);
		}

	}

	/**
	 * Close.
	 */
	private void close() {
		try {
			outToServer.close();
			fromServer.close();
			socket.close();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.uwaterloo.interviewme.requsthandler.RequestHandler#login(java.lang.String,
	 * java.lang.String)
	 */
	@Override
	public boolean login(String user, String pwd) throws ServerException {
		Map<String, String> params = new HashMap<String, String>();
		params.put(RequestKeys.OP_CODE, OpCode.Authenication.name());
		params.put(RequestKeys.USER_NAME, user);
		params.put(RequestKeys.PWD, pwd);
		Request request = new Request(params);

		open();
		outToServer.println(request.toString());
		String gsonString = serverReadline();
		close();

		Map<String, String> result = new Response(gsonString).getResult();
		return (ResponseKeys.SUCCESS.equals(result.get(ResponseKeys.RESULT))) ? true : false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.uwaterloo.interviewme.requsthandler.RequestHandler#getAllInterview(java.lang.String)
	 */
	@Override
	public Collection<Interview> getAllInterview(String user) throws ServerException {
		Map<String, String> params = new HashMap<String, String>();
		params.put(RequestKeys.OP_CODE, OpCode.GetAllInterview.name());
		params.put(RequestKeys.USER_NAME, user);
		Request request = new Request(params);

		List<Interview> interviews = new ArrayList<Interview>();
		open();
		outToServer.println(request);
		for (;;) {
			Map<String, String> result = new Response(serverReadline()).getResult();
			if (result.get(ResponseKeys.TYPE).equals(ResponseKeys.LIST)) {
				interviews.add(new Interview(result.get(InterviewKeys.INTERVIEW_ID), result.get(InterviewKeys.COMPANY_NAME), result
						.get(InterviewKeys.POSITION), result.get(InterviewKeys.LOCATION), result.get(InterviewKeys.TIME)));
			} else if (result.get(ResponseKeys.TYPE).equals(ResponseKeys.END)) {
				break;
			}
		}
		return interviews;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.uwaterloo.interviewme.requsthandler.RequestHandler#getOneInterview(java.lang.String,
	 * java.lang.String)
	 */
	@Override
	public DetailInfo getOneInterview(String user, String interivewID) throws ServerException {
		Map<String, String> params = new HashMap<String, String>();
		params.put(RequestKeys.OP_CODE, OpCode.GetOneInterview.name());
		params.put(RequestKeys.USER_NAME, user);
		params.put(RequestKeys.INTERVIEW_ID, interivewID);
		Request request = new Request(params);

		open();
		outToServer.println(request.toString());
		String gsonString = serverReadline();
		close();

		Map<String, String> result = new Response(gsonString).getResult();

		DetailInfo detailInfo = null;
		if (result.get(ResponseKeys.TYPE).equals(ResponseKeys.ONE)) {
			detailInfo = new DetailInfo(result.get(DetailInfoKeys.TYPE), result.get(DetailInfoKeys.STATUS),
					result.get(DetailInfoKeys.LENGTH), result.get(DetailInfoKeys.JOB_DESC));
		}
		return detailInfo;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.uwaterloo.interviewme.requsthandler.RequestHandler#setSyncInterval(java.lang.String,
	 * int)
	 */
	@Override
	public void setSyncInterval(String user, int interval) throws ServerException {
		Map<String, String> params = new HashMap<String, String>();
		params.put(RequestKeys.OP_CODE, OpCode.SetSyncInterval.name());
		params.put(RequestKeys.USER_NAME, user);
		Request request = new Request(params);

		open();
		outToServer.println(request.toString());
		close();
	}

	/**
	 * Server readline.
	 * 
	 * @return the string
	 */
	private String serverReadline() {
		String ret = null;
		try {
			ret = fromServer.readLine();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return ret;
	}

}
